using System;
using System.Collections;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;
using Utils = PHSRAG.Insight21.InsightUtilities;

namespace PHSRAG.Insight21.COI
{
    /// <summary>
    /// This page will be presented only to the users with suprevisor and/super user access rights.
    /// The search criteria will enable the logged in user with required permission to search for the user directly under the hierarchy.
    /// This page will also enable the logged in user to impersonate as any supervisor or reviewer in the system.
    /// The search will yield the summary of the user and the COI matching the criteria.
    /// </summary>
    public partial class HierarchyMaintenance : BasePage
    {
        #region custom event

        //This event will be captured by the base page(Hierarchy maintenance page)that will be raised by the userimpersonation user control.
        public event EventHandler ClearSelectionClicked;

        #endregion

        #region Constants

        private const string AnnunciatorTitle = "The following error(s) occurred...";
        private const string COIIdField = "COIId";
        private const string ConfirmationFlag = "ConfirmationFlag";
        private const string HMaintenancePageIndexKey = "HMaintenancePageIndexKey_26CA81B1-D0A6-4e9b-A305-3B2C8C4BA4A1";
        private const string PersonIdField = "PersonId";
        private const int referingPage = 1;

        #endregion

        #region Instance variable (Protected)

        protected CommonSearch commonSearch;

        #endregion

        #region Instance Variables (Private)

        private ICachePolicy cachePolicy;

        /// <summary>
        /// boolean variable to determine whether not to notify
        /// </summary>
        private bool confirmAction;

        /// <summary>
        /// Id column(Datkey column) for the data source
        /// </summary>
        private string keyField = "Id";

        private ICachePolicy pageCachePolicy;

        /// <summary>
        /// Person Id to whom the page actions to hinge on.
        /// </summary>
        private int parentId;

        #endregion

        #region property variables		

        #endregion

        # region Get/Set properties for search criteria

        /// <summary>
        /// This property will fetch the required COI Roles to be bound to the dropdown list from the application cache.
        /// </summary>
        protected ListItemCollection GetCOIRoles
        {
            get
            {
                RefCodes refCodes =
                    (RefCodes) ((ICachePolicy) Page.Application[Names.ApplicationCachePolicyKey]).GetCachedObject(RefCodes.CacheKey);

                ArrayList COIRoles =
                    refCodes.GetSortedRefCodes(Constants.COIRole.Domain, Constants.COIRole.AttributeOrder);

                ListItemCollection lc = new ListItemCollection();
                lc.Add(new ListItem("Select", "Default"));
                foreach (RefCode rf in COIRoles)
                {
                    lc.Add(new ListItem(rf.Meaning, rf.Code));
                }
                //CDS.RefCode defaultRole=new PHSRAG.Insight21.CDS.RefCode("Default","Default","Select",'Y',null); 
                //COIRoles.Insert(0,defaultRole);
                return lc;
            }
        }


        protected ListItemCollection GetHierarchyTypes
        {
            get
            {
                DataTable dt = DataAccess.GetDataTable(DataAccess.GetConnectionString(), "GetCOIHierarchyTypes", null);
                //GetHierarchyTypesDT();

                ListItemCollection lc = new ListItemCollection();
                //lc.Add(new ListItem("Select", "Default"));

                foreach (DataRow dr in dt.Rows)
                {
                    lc.Add(new ListItem(dr["Description"].ToString(), dr["Id"].ToString()));
                } 
                return lc;
               
            }
        }


        private DataTable GetHierarchyTypesDT()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Id", Type.GetType("System.Int32"));
            dt.Columns.Add("Description", Type.GetType("System.String"));
            DataRow dr = dt.NewRow();
            dr["Id"] = 1;
            dr["Description"] = "Board";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["Id"] = 2;
            dr["Description"] = "Committee";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["Id"] = 3;
            dr["Description"] = "Institutional";
            dt.Rows.Add(dr);

            return dt;

        }


        /// <summary>
        /// Gets the parentId(for whom the results had to be shown in the grid)
        /// </summary>
        private int ParentId
        {
            get { return parentId; }
            set { parentId = value; }
        }

        /// <summary>
        /// Get delegate status of the loggedIn user.
        /// </summary>
        private bool IsLoggedInUserADelegate
        {
            get
            {
                int loggedInUserId = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;
                return COIUserSummary.IsLoggedInUserADelegate(loggedInUserId, DataAccess.GetConnectionString());
            }
        }

        #endregion

        #region Private Properties

        /// <summary> 
        /// Gets the COIUserSummary object relevant to the passed in search criteria.
        /// </summary>
        private COIUserSummary COIUserSummary
        {
            get
            {
                COIUserSummary cOIUserSummary = null;
                if (PerformBinding())
                {
                    cOIUserSummary = GetCOIUserSummaryFromCache;
                    CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                    SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                    if (cOIUserSummary == null)
                    {
                        cOIUserSummary = new COIUserSummary(cachePolicy);
                    }
                    if ((searchContext != null) && usersList.EditItemIndex == -1)
                    {
                        cOIUserSummary.Load(DataAccess.ConnectionString, searchCriteria, ParentId, referingPage);
                        cOIUserSummary.Cache();
                    }
                }
                return cOIUserSummary;
            }
        }

        /// <summary>
        /// Get/Set the current page within the datagrid for display. This information persists across page loads.
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.HierarchyMaintenancePageKey) as Hashtable;
                return (h == null || h[HMaintenancePageIndexKey] == null) ? 0 : (int) h[HMaintenancePageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.HierarchyMaintenancePageKey) as Hashtable ?? new Hashtable();
                h[HMaintenancePageIndexKey] = value;
                usersList.CurrentPageIndex = value;
                pageCachePolicy.Cache(Keys.HierarchyMaintenancePageKey, h);
            }
        }

        /// <summary>
        /// Gets the Cached COIUserSummary object
        /// </summary>
        private COIUserSummary GetCOIUserSummaryFromCache
        {
            get { return cachePolicy.GetCachedObject(COIUserSummary.CacheKey) as COIUserSummary; }
        }

        #endregion

        #region private methods

        /// <summary>
        /// Uncaches all objects with data for this page.
        /// </summary>
        private void PurgeCache()
        {
            System.Diagnostics.Trace.WriteLine("Purging Supervisor Summary...");
            COIUserSummary coiUserSummary = GetCOIUserSummaryFromCache;
            if (coiUserSummary != null)
            {
                coiUserSummary.Purge();
                cachePolicy.UnCache(COIUserSummary.CacheKey);
            }
        }

        /// <summary>
        /// Loads the COIUser Summary details only for those to displayed on the page.
        /// </summary>
        private void LoadDataGrid()
        {
            SetPersonIdToImpersonate();
            COIUserSummary cOIUserSummary = COIUserSummary;
            if (cOIUserSummary != null)
            {
                usersList.VirtualItemCount = bottomPager.RecordCount =
                    topPager.RecordCount = cOIUserSummary.Count;
                int currentPageIndex = CurrentPageIndex;
                int pageCount = (topPager.RecordCount/usersList.PageSize) +
                    (((topPager.RecordCount%usersList.PageSize) == 0) ? 0 : 1);
                bottomPager.PageCount = topPager.PageCount = pageCount;
                bottomPager.CurrentPage = topPager.CurrentPage = currentPageIndex + 1;
                
                DataTable table = cOIUserSummary.GetSummaryList(
                    currentPageIndex*usersList.PageSize, usersList.PageSize, DataAccess.ConnectionString,referingPage);
                usersList.DataSource = table;
                usersList.DataKeyField = keyField;
                usersList.DataBind();

                if (table.Rows.Count == 0)
                {
                    gridContainer.Visible = false;
                    annunciator.Message = "The search criteria yielded no results.";
                }
                else
                {
                    gridContainer.Visible = true;
                    annunciator.Message = string.Empty;
                    recordCount.Text = topPager.RecordCount.ToString();
                    ManagePagination();
                    ManageNavigationLinks();
                }
            }
            else
            {
                gridContainer.Visible = false;
                annunciator.Message = "The search criteria yielded no results.";
            }
        }


        /// <summary>
        /// Initilize the first record, last record and current page values for the pager controls.
        /// Set the current page index to 0 and manage navigation links.
        /// </summary>
        private void InitializePager()
        {
            bottomPager.FirstRecord = topPager.FirstRecord = 1;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(usersList.PageSize, usersList.Items.Count);
            bottomPager.CurrentPage = topPager.CurrentPage = 1;
            CurrentPageIndex = 0;
            ManageNavigationLinks();
        }

        /// <summary>
        /// Enables or Disables links to other pages within the grid
        /// </summary>
        private void ManageNavigationLinks()
        {
            bottomPager.EnableFirstPage = topPager.EnableFirstPage =
                bottomPager.EnablePreviousPage = topPager.EnablePreviousPage =
                    (usersList.CurrentPageIndex != 0);

            bottomPager.EnableLastPage = topPager.EnableLastPage =
                bottomPager.EnableNextPage = topPager.EnableNextPage =
                    (usersList.CurrentPageIndex != (topPager.PageCount - 1));
        }

        /// <summary>
        /// Pagination management
        /// </summary>
        private void ManagePagination()
        {
            int currentPageIndex = CurrentPageIndex;
            usersList.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*usersList.PageSize;
            bottomPager.FirstRecord = topPager.FirstRecord = startIndex + 1;

            int lastRecord = COIUserSummary.Count;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(startIndex + usersList.PageSize, lastRecord);
        }

        /// <summary>
        /// Retrieves the CommonSearchContext from the cache and
        /// performs a hierarchy maintenance search.
        /// </summary>
        private void PerformSearch()
        {
            CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            if (searchContext != null)
            {
                LoadDataGrid();
            }
        }

//		/// <summary>
//		/// This method will perform a search based on the search criteria verison.
//		/// Note:If the search criteria verison does not change, then the controls are not going to be reloaded.
//		/// This does not go good while imepersonating a user, since the search criteria never gets changed,but the datagrid should be reloaded with the result set for the impersonated user.
//		/// For the above reason,the searchcriteriaversion should be manually set to -1.
//		/// Why set to '-1' and not '0'?
//		/// Assume that a super user logs in(He/she will be able to impersonate as anybody in the system.
//		/// The follwoing actions will be performed.
//		/// Step1:Users directly under him/her will be listed in the grid.(no search criteria exists).
//		///		 --Search criteria verison=0.
//		/// Step2:Assuming the super user directly impersonates as a supervisor/reviewer without performing any serach on his list of users.
//		///		 --Search criteria version is still 0 and no serach will be performed to reload the grid.		
//		/// </summary>
//		/// <param name="clearSearchVersion"></param>
//		private void Search(bool clearSearchVersion)
//		{
//			PerformSearch();			
//		}

        /// <summary>
        /// Determine whether or not the grid should be bound for the logged in user to see people directly under him/her.
        /// Note:
        /// If Logged in user is a supervisor(+ superuser),then the grid will be bound with people directly under the logged in user.
        /// If Logged in User is only a super user, then he/she will not have users under hime/her.
        /// </summary>
        /// <returns></returns>
        private bool PerformBinding()
        {
            bool canBind = true;
            Hashtable incomingPageHash =
                cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if ((incomingPageHash != null) && incomingPageHash.ContainsKey(Keys.ImpersonationIdKey))
            {
                if (((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId == Convert.ToInt32(incomingPageHash[Keys.ImpersonationIdKey]))
                {
                    if ((((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0
                        && (((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.Supervisor) == 0)
                    {
                        //logged in user has both super-user and supervisor access rights,hence load grid.
                        canBind = false;
                    }
                }
            }
            else
            {
                if ((((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0
                    && (((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.Supervisor) == 0)
                {
                    //logged in user has both super-user and supervisor access rights,hence load grid.
                    canBind = false;
                }
            }
            return canBind;
        }

        /// <summary>
        /// Removes the parent child relationship
        /// </summary>
        /// <param name="childAdmPersonId">Child person Id</param>
        private void RemovePerson(int childAdmPersonId,int HierarchyTypeId)
        {
            try
            {
                if (ParentId != 0)
                {
                    COIUserSummary.RemoveUserFromHierarchy(DataAccess.ConnectionString, ParentId, childAdmPersonId,HierarchyTypeId);
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Updates the person details
        /// </summary>
        private void UpdatePerson(int PersonId, bool isOutsideMember, string cOIRoleSelected,int intHierarchyTypeId)
        {
            try
            {
                COIUser coiUser = new COIUser(cachePolicy);
                coiUser.Load(DataAccess.ConnectionString, PersonId, parentId, hdnHierarchyTypeId.Value);
                coiUser.IsOutsideMember = isOutsideMember;
                coiUser.COIRole = cOIRoleSelected;
                coiUser.HierarchyTypeId = intHierarchyTypeId;
                coiUser.Dirty = true;
                coiUser.Save(DataAccess.ConnectionString);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = AnnunciatorTitle;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }

        /// <summary>
        /// This method will determine whether or not to dispaly the Impersonation control depending on the access rights.
        /// Note:If Logged in user is a Super-User then shows Impersonation control.
        /// </summary>
        private void ShowOrHideControls()
        {
            if ((((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int)ModuleRoleBit.SuperUser) != 0
                || (IsLoggedInUserADelegate)
                )
            {
                impersonationPanel.Visible = true;
                supervisorInstruction.Visible = false;
            }
        }

        /// <summary>
        /// The Impersonation is handled using the incoming page cache.
        /// Note: sets the parentId(property variable) to the personID available in incoming cache.
        /// If one does not exist in the incoming cache ,then the logged in user's admPersonId will be set to the parent id.
        /// </summary>
        private void SetPersonIdToImpersonate()
        {
            Hashtable incomingPageHash =
                cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            ParentId = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;

            if (incomingPageHash != null && incomingPageHash.ContainsKey(Keys.ImpersonationIdKey))
            {
                ParentId = Convert.ToInt32(incomingPageHash[Keys.ImpersonationIdKey]);
                addUser.Visible = ((((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int)ModuleRoleBit.SuperUser) != 0) ? true : false;
                supervisorInstruction.Visible = ((((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int)ModuleRoleBit.Supervisor) != 0 || IsLoggedInUserADelegate) ? true : false;
            }
        }

        /// <summary>
        /// Removes the personId from the incoming cache that was added during the page life cycle.
        /// Note:This method will be called when the page goes out of scope.
        /// </summary>
        private void RemovePersonIdFromIncomingCache()
        {
            Hashtable outgoingData =
                cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (outgoingData != null)
            {
                if (outgoingData.ContainsKey(Keys.ImpersonationIdKey))
                {
                    outgoingData.Remove(Keys.ImpersonationIdKey);
                    outgoingData.Add(Keys.ImpersonationIdKey, ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId);
                    pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                }
            }
        }

        #endregion

        #region Web Form Designer generated code

        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            EnsureChildControls();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];

            coiSubNavigation.Navigate += new CommandEventHandler(OnSubNavigate);
            this.downloadBar.FailedAction += new CommandEventHandler(OnDownloadFailed);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.breadCrumb.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.topPager.FirstPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnFirstPage);
            this.topPager.PreviousPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnPreviousPage);
            this.topPager.NextPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnNextPage);
            this.topPager.LastPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnLastPage);
            this.usersList.ItemCreated += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemCreated);
            this.usersList.PageIndexChanged += new System.Web.UI.WebControls.DataGridPageChangedEventHandler(this.OnPageIndexChanged);
            this.usersList.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnCancelChange);
            this.usersList.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnEditDetail);
            this.usersList.SortCommand += new System.Web.UI.WebControls.DataGridSortCommandEventHandler(this.OnSort);
            this.usersList.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnUpdateChange);
            this.usersList.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.bottomPager.FirstPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnFirstPage);
            this.bottomPager.PreviousPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnPreviousPage);
            this.bottomPager.NextPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnNextPage);
            this.bottomPager.LastPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnLastPage);
            this.addUser.Click += new ImageClickEventHandler(OnAddUser);
            this.Load += new System.EventHandler(this.OnPageLoad);
            this.userImpersonation.ImpersonateClicked += new EventHandler(OnImpersonate);
            this.ClearSelectionClicked += new EventHandler(this.userImpersonation.ResetDropDownSelection);
            this.userImpersonation.FindSupervisorsClicked += new EventHandler(OnFindSupervisor);
        }

        #endregion

        #region Search event handler

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Clear Selection" buttion is clicked upon.
        /// The control clears the criteria (specific to this module).
        /// Since in the page life-cycle, the Load occurs before the Clear event, we have to instigate a re-load of the
        /// data grid to refelect the fact that the search criteria has been cleared.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            try
            {
                ParentId = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;
                Hashtable outgoingData = new Hashtable();
                outgoingData.Add(Keys.ImpersonationIdKey, ParentId);
                pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                PerformSearch();
                if (ClearSelectionClicked != null)
                {
                    ClearSelectionClicked(sender, e);
                }
                addUser.Visible = false;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Search" buttion is clicked upon.
        /// Initiates the search by calling PerformSearch
        /// </summary>
        /// <param name="args">Argument associated with the event (contains the search criteria dictionary)</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            try
            {
                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Page Event Handlers

        /// <summary>
        /// Registers a hidden field used to determine on page load whether to refresh the Confirmnotification javascript.
        /// </summary>
        /// <param name="e">arguments to render.</param>
        protected override void OnPreRender(EventArgs e)
        {
            try
            {
                base.OnPreRender(e);
                ClientScript.RegisterHiddenField(ConfirmationFlag, confirmAction.ToString());
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// The page load event handler
        /// </summary>
        /// <param name="sender">Sender,that raised the event</param>
        /// <param name="e">argiments related to the sender</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            try
            {
                

                annunciator.Message = string.Empty;
                annunciator.Title = string.Empty;
                breadCrumb.Add("Hierarchy Maintenance", Settings.
                    GetKeyValue("SubNavigation.CoI.HierarchyMaintenanceURL", string.Empty),
                    Settings.GetKeyValue("BreadCrumb.SummaryPageLevel", 1));
                string confirmData = Request.Form[ConfirmationFlag];
                confirmAction = (confirmData != null && confirmData == "True");
                ShowOrHideControls();

                if (!IsPostBack && postbackGuard.IsValid)
                {
                    usersList.PageSize = Settings.GetKeyValue("COIDataGrid.ItemsPerPage", 20);
                    CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
                    if (CurrentPageIndex == 0)
                    {
                        InitializePager();
                    }
                    UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                    LoadDataGrid();
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
            finally
            {
                coiSubNavigation.SelectedLink = "Hierarchy Maintenance";
                coiSubNavigation.AccessLevel = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask;
                coiSubNavigation.IsLoggedInUserADelegate = IsLoggedInUserADelegate;
            }
        }

        /// <summary>
        /// Event raised on binding the datagrid with the datasource
        /// Note:manages displaying the editable fields on edit item action.
        /// </summary>
        /// <param name="sender">owner of the event</param>
        /// <param name="e">arguments with respect to the event</param>
        private void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.EditItem)
                {
                    CheckBox outsideMember = e.Item.Cells[(int) ColumnIndex.OutSideTrsustee].Controls[1]
                        as CheckBox;
                    if (outsideMember != null)
                    {
                        if (((DataRowView) e.Item.DataItem).Row.ItemArray[3] != DBNull.Value)
                        {
                            bool isTrustee = (bool) ((DataRowView) e.Item.DataItem).Row.ItemArray[3];
                            outsideMember.Checked = isTrustee;
                        }
                        else
                        {
                            outsideMember.Checked = false;
                        }
                    }
                    CheckBox remove = e.Item.Cells[(int) ColumnIndex.Remove].Controls[1]
                        as CheckBox;

                    DropDownList roles;
                    DropDownList ddlHeirarchyTypes;

                    if (e.Item.ItemIndex == usersList.EditItemIndex)
                    {
                        roles = e.Item.Cells[(int) ColumnIndex.Role].
                            FindControl("roles") as DropDownList;
                        if (roles != null)
                        {
                            string role = ((DataRowView) e.Item.DataItem).Row.ItemArray[4].ToString().Trim();
                            role = (role == "") ? "Default" : role;
                            roles.SelectedValue = role;
                            roles.Visible = true;
                        }

                        ddlHeirarchyTypes = e.Item.Cells[(int)ColumnIndex.HierarchyType].FindControl("ddlHierarchyTypes") as DropDownList;
                        if (ddlHeirarchyTypes != null)
                        {
                            string strHierarchyType = ((DataRowView)e.Item.DataItem).Row.ItemArray[5].ToString().Trim();
                            strHierarchyType = (strHierarchyType == "") ? "3" : strHierarchyType;
                            ddlHeirarchyTypes.SelectedValue = strHierarchyType;
                            ddlHeirarchyTypes.Visible = true;
                        }

                        if (outsideMember != null)
                        {
                            outsideMember.Enabled = true;
                        }

                        if (remove != null)
                        {
                            remove.Enabled = true;
                            remove.Attributes.Add("onClick", "return ConfirmAction('" + remove.ClientID + "','" + ((Label) e.Item.Cells[(int) ColumnIndex.Name].Controls[1]).Text.Replace("'", "\\'") + "')");
                        }
                    }
                    else
                    {
                        Label roleCode = e.Item.Cells[(int) ColumnIndex.Role].FindControl("roleLabel") as Label;
                        if (roleCode != null)
                        {
                            ListItemCollection coiRoles = GetCOIRoles;
                            foreach (ListItem  lc in coiRoles)
                            {
                                if (lc.Value == roleCode.Text)
                                {
                                    roleCode.Text = lc.Text;
                                    roleCode.Visible = true;
                                    break;
                                }
                            }

                            if (outsideMember != null)
                            {
                                outsideMember.Enabled = false;
                            }
                            remove.Checked = false;
                            remove.Enabled = false;
                        }
                        //Hierarchy Type
                        Label lblHierarchyType = e.Item.Cells[(int)ColumnIndex.HierarchyType].FindControl("lblHierarchyType") as Label;
                        if (lblHierarchyType != null)
                        {
                            ListItemCollection lcHierarchyTypes = GetHierarchyTypes;
                            foreach (ListItem lc in lcHierarchyTypes)
                            {
                                if (lc.Value == lblHierarchyType.Text)
                                {
                                    lblHierarchyType.Text = lc.Text;
                                    lblHierarchyType.Visible = true;
                                    break;
                                }
                            }
                        }
                        Label isOutsideTrustee = e.Item.Cells[(int) ColumnIndex.OutSideTrsustee].FindControl("outSideTrustee") as Label;
                        if (isOutsideTrustee != null)
                        {
                            isOutsideTrustee.Text = (isOutsideTrustee.Text.ToLower().Trim() == "true") ? "Y" : "N";
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Resets the index of the item being edited to -1 and refreshes the usersList grid
        /// </summary>
        /// <param name="source">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnCancelChange(object source, DataGridCommandEventArgs e)
        {
            try
            {
                usersList.EditItemIndex = -1;
                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Sets the index of the item being edited and refreshes the usersList grid
        /// </summary>
        /// <param name="source">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnEditDetail(object source, DataGridCommandEventArgs e)
        {
            try
            {
                usersList.EditItemIndex = e.Item.ItemIndex;
                //Hierarchy Type
                Label lblHierarchyType = e.Item.Cells[(int)ColumnIndex.HierarchyType].FindControl("lblHierarchyType") as Label;
                
                if (lblHierarchyType != null)
                {
                    ListItemCollection lcHierarchyTypes = GetHierarchyTypes;
                    foreach (ListItem lc in lcHierarchyTypes)
                    {
                        if (lc.Text == lblHierarchyType.Text)
                        {
                            hdnHierarchyTypeId.Value = lc.Value;
                         
                            break;
                        }
                    }
                }
                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// The item being edited gets saved to the database with by calling Save() on COIUser. The index of the item is then reset to -1 
        /// and the usersList grid is refreshed to reflect the updates
        /// </summary>
        /// <param name="source">source of the event</param>
        /// <param name="e">arguments of the event</param>
        private void OnUpdateChange(object source, DataGridCommandEventArgs e)
        {
            try
            {
                SetPersonIdToImpersonate();
                if (((CheckBox) e.Item.Cells[(int) ColumnIndex.Remove].Controls[1]).Checked)
                {
                    if (confirmAction)
                    {
                        RemovePerson(Convert.ToInt32(usersList.DataKeys[e.Item.ItemIndex]),Convert.ToInt32(((DropDownList)e.Item.Cells[(int)ColumnIndex.HierarchyType].Controls[1]).SelectedValue));
                    }
                }
                else
                {
                    UpdatePerson(Convert.ToInt32(usersList.DataKeys[e.Item.ItemIndex]), 
                                 ((CheckBox) e.Item.Cells[(int) ColumnIndex.OutSideTrsustee].Controls[1]).Checked,
                                 (((DropDownList) e.Item.Cells[(int) ColumnIndex.Role].Controls[1]).SelectedValue.Trim().ToLower() == "default") ? string.Empty : ((DropDownList) e.Item.Cells[(int) ColumnIndex.Role].Controls[1]).SelectedValue.Trim(),
                                 (((DropDownList)e.Item.Cells[(int)ColumnIndex.HierarchyType].Controls[1]).SelectedIndex == -1) ? (int)COIUser.HierarchyType.Institutional : Convert.ToInt32(((DropDownList)e.Item.Cells[(int)ColumnIndex.HierarchyType].Controls[1]).SelectedValue)
                                 );
                    
                }
                usersList.EditItemIndex = -1;

                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Sort event handler
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnSort(object source, DataGridSortCommandEventArgs e)
        {
            try
            {
                if (e.SortExpression != string.Empty)
                {
                    COIUserSummary cOIUserSummary = GetCOIUserSummaryFromCache ?? new COIUserSummary(cachePolicy);

                    cOIUserSummary.SortColumn = e.SortExpression;
                    cOIUserSummary.SortAscending = (cOIUserSummary.SortColumn == e.SortExpression) ? !cOIUserSummary.SortAscending : cOIUserSummary.SortAscending;
                    cOIUserSummary.Cache();
                    CurrentPageIndex = 0;
                    LoadDataGrid();
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// This event is raised when the page index property is changed on the pager control.
        /// The page's DataGrid is reloaded with the data belonging to page specified by the index.
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnPageIndexChanged(object source, DataGridPageChangedEventArgs e)
        {
            try
            {
                usersList.CurrentPageIndex = e.NewPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the FirstPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the first page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnFirstPage(object sender, CommandEventArgs e)
        {
            try
            {
                CurrentPageIndex = 0;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the LastPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the last page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnLastPage(object sender, CommandEventArgs e)
        {
            try
            {
                int lastPageIndex = topPager.PageCount - 1;
                CurrentPageIndex = lastPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the NextPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the next page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnNextPage(object sender, CommandEventArgs e)
        {
            try
            {
                ++CurrentPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the PreviousPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the previous page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnPreviousPage(object sender, CommandEventArgs e)
        {
            try
            {
                --CurrentPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// If the item being created is the data grid header, do the following:
        /// Add the appropriate sort symbol to denote ascending/descending sequence for the current sort column.
        /// This requires us to locate the cell which corresponding to the column within the collection of TableCell
        /// maintained by the DataGridItem which is under creation. That collection is indexed numerically, the value being
        /// the position of the column within the columns collection maintained by the data grid.
        /// One simple way to do this is to create static mapping between the name of the column and its index. However, this
        /// suffers from the shortcoming that if the sequence of columns is changed on the page, the static binding MUST
        /// be changed too. If they get out of sync, we would be sorting on inappropriate columns!
        /// To avoid this, and to render the code independent of how the page gets managed, we will build a Hashtable of
        /// column indeces, keyed by the sort expression of each column. That way, we could do a quick lookup to get the
        /// index of a column and set the sort symbol on that column.
        /// If the item being created is a data row item, disable its view state.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Header)
                {
                    COIUserSummary cOIUserSummary = GetCOIUserSummaryFromCache;
                    Label sortSymbol = new Label();
                    sortSymbol.Text = (cOIUserSummary.SortAscending) ? InsightUtilities.Constants.SortAscendingText : InsightUtilities.Constants.SortDescendingText;
                    sortSymbol.Font.Name = InsightUtilities.Constants.SortSymbolFontName;

                    Hashtable columnMap = new Hashtable();
                    foreach (DataGridColumn column in usersList.Columns)
                    {
                        columnMap[column.SortExpression] = usersList.Columns.IndexOf(column);
                    }

                    string sortColumn = cOIUserSummary.SortColumn;
                    if (columnMap.ContainsKey(sortColumn))
                    {
                        (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                    }
                }
                else if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                {
                    if ((((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) == 0)
                    {
                        (usersList.Columns[(int) ColumnIndex.Edit]).Visible = false;
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header/breadcrumb navigation.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                PurgeCache();
                coiSubNavigation.Reset();
                RemovePersonIdFromIncomingCache();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Purges the cache before the COI subnavigation header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnSubNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                PurgeCache();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        /// <summary>
        /// This button click event will redirect the user to the AddCOIUser page after setting the personId in the incoming cache.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAddUser(object sender, ImageClickEventArgs e)
        {
            try
            {
                SetPersonIdToImpersonate();
                if (ParentId != 0)
                {
                    CommonSearchContext searchContext = (CommonSearchContext)cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                    SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                    //Set the Person id in incoming cache.
                    Hashtable outgoingData = new Hashtable();
                    outgoingData.Add(Keys.ImpersonationIdKey, ParentId);
                    outgoingData.Add(Keys.HierarchyTypeIdKey, searchCriteria[Constants.COISearch.HierarchyType]);
                    pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                    Response.Redirect(Settings.GetKeyValue("SubNavigation.CoI.AddUsersURL", string.Empty), false);
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// This  is the custom event raised by the UserImpersonation control.
        /// As the page load of the user control happens after the loading the page,
        /// The base page(containing the user control)has to be reloaded to reflect the changes from the user control.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnImpersonate(object sender, EventArgs e)
        {
            try
            {
                CurrentPageIndex = 0;
                PerformSearch();
                addUser.Visible = ((((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int)ModuleRoleBit.SuperUser) != 0) ? true : false;
                supervisorInstruction.Visible = ((((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int)ModuleRoleBit.Supervisor) != 0 || IsLoggedInUserADelegate) ? true : false;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// This  is the custom event raised by the UserImpersonation control.
        /// As the page load of the user control happens after the loading the page,
        /// The base page(containing the user control)has to be reloaded to reflect the changes from the user control.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnFindSupervisor(object sender, EventArgs e)
        {
            gridContainer.Visible = false;
            commonSearch = (CommonSearch) helpContainer.FindControl("commonSearch");
            commonSearch.UpdateSearchCriteria();
            addUser.Visible = false;
        }

        #endregion

        #region ColumnIndex Enum

        /// <summary>
        /// Provides indexes used in the datagrid for specific columns
        /// </summary>
        private enum ColumnIndex
        {
            /// <summary>Name column index </summary>
            Name,
            /// <summary>UserName column index </summary>
            UserName,
            /// <summary>Role column index </summary>
            Role,
            /// <summary>HierarchyType column index.</summary>
            HierarchyType,
            /// <summary>Outside trustee(Template column) index </summary>
            OutSideTrsustee,
            /// <summary>Template(Remove) column index </summary>
            Remove,
            /// <summary>Template(Edit) column index </summary>
            Edit
        }

        #endregion

        //#region HierarchyType Enum

        //private enum HeirarchyType
        //{
        //    Board = 1,
        //    Committe,
        //    Institutional,
        //}

        //#endregion HierarchyType Enum
    }
}